"""
认证服务
"""
from datetime import timedelta
from typing import Optional, Dict, Any
from app.core.config import settings
from app.core.security import create_access_token
from app.schemas.user import LoginRequest, UserSchema
from app.models.user import User
from app.crud.user import authenticate_user, get_user_by_username
from sqlalchemy.orm import Session
from fastapi import HTTPException, status
import logging
import time

from app.crud import user

logger = logging.getLogger(__name__)

class AuthService:
    """认证服务类"""
    
    def __init__(self, db: Session):
        self.db = db
    
    def login(self, login_request: LoginRequest) -> Dict[str, Any]:
        """用户登录"""
        try:
            # 添加超时机制
            start_time = time.time()
            
            # 验证用户身份
            user = authenticate_user(self.db, login_request.username, login_request.password)
            
            # 检查是否超时
            if time.time() - start_time > 10:  # 10秒超时
                logger.warning(f"登录验证超时: {login_request.username}")
                raise HTTPException(
                    status_code=status.HTTP_408_REQUEST_TIMEOUT,
                    detail="登录验证超时，请稍后重试"
                )
                
            if not user:
                logger.warning(f"登录失败: 用户名或密码错误 - {login_request.username}")
                raise HTTPException(
                    status_code=status.HTTP_401_UNAUTHORIZED,
                    detail="用户名或密码错误"
                )
            
            # 创建访问令牌
            access_token_expires = timedelta(minutes=settings.ACCESS_TOKEN_EXPIRE_MINUTES)
            access_token = create_access_token(
                data={"username": user.username, "user_id": user.id},
                expires_delta=access_token_expires
            )
            
            # 转换用户信息（移除敏感字段）
            user_info = user.to_dict()
            user_info.pop('password', None)
            
            logger.info(f"用户登录成功: {user.username}")
            
            return {
                "token": access_token,
                "user": user_info,
                "expiresIn": settings.ACCESS_TOKEN_EXPIRE_MINUTES * 60
            }
        except HTTPException as e:
            raise e
        except Exception as e:
            logger.error(f"登录过程中发生错误: {str(e)}")
            raise HTTPException(
                status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
                detail="登录失败，请稍后重试"
            )
    
    def get_user_info(self, username: str) -> Dict[str, Any]:
        """获取用户信息"""
        try:
            user = get_user_by_username(self.db, username)
            if not user:
                logger.warning(f"获取用户信息失败: 用户不存在 - {username}")
                raise HTTPException(
                    status_code=status.HTTP_404_NOT_FOUND,
                    detail="用户不存在"
                )
            
            user_info = user.to_dict()
            user_info.pop('password', None)
            
            logger.info(f"获取用户信息成功: {username}")
            
            return user_info
        except HTTPException:
            raise
        except Exception as e:
            logger.error(f"获取用户信息过程中发生错误: {str(e)}")
            raise HTTPException(
                status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
                detail="获取用户信息失败，请稍后重试"
            )
    
    def refresh_token(self, username: str, user_id:int) -> Dict[str, Any]:
        """刷新访问令牌"""
        try:
            access_token_expires = timedelta(minutes=settings.ACCESS_TOKEN_EXPIRE_MINUTES)
            new_token = create_access_token(
                data={"username": username, "user_id": user_id},
                expires_delta=access_token_expires
            )
            
            logger.info(f"令牌刷新成功: {username}")
            
            return {
                "token": new_token,
                "expiresIn": settings.ACCESS_TOKEN_EXPIRE_MINUTES * 60
            }
        except Exception as e:
            logger.error(f"令牌刷新过程中发生错误: {str(e)}")
            raise HTTPException(
                status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
                detail="令牌刷新失败，请稍后重试"
            )